package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.constant.ProductConst;
import com.atguigu.gmall.list.feign.GoodsFeign;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.ManagerService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * projectName: gmall
 *
 * @author: 陈鹏
 * time: 2022/9/21 16:14 星期三
 * description:后台管理页面使用的服务层的实现类
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Log4j2
public class ManagerServiceImpl implements ManagerService {

    @Resource
    private BaseCategory1Mapper baseCategory1Mapper;
    /**
     * 查询所有的一级分类
     *
     * @return
     */
    @Override
    public List<BaseCategory1> getBaseCategory1() {
        return baseCategory1Mapper.selectList(null);
    }


    @Resource
    private BaseCategory2Mapper baseCategory2Mapper;
    /**
     * 根据一级分类ID查询二级分类
     *
     * @param c1Id
     * @return
     */
    @Override
    public List<BaseCategory2> getBaseCategory2(Long c1Id) {
        return baseCategory2Mapper.selectList(
                new LambdaQueryWrapper<BaseCategory2>()
                        .eq(BaseCategory2::getCategory1Id,c1Id));
    }

    @Resource
    private BaseCategory3Mapper baseCategory3Mapper;
    /**
     * 根据二级分类ID查询三级分类
     *
     * @param c2Id
     * @return
     */
    @Override
    public List<BaseCategory3> getBaseCategory3(Long c2Id) {
        return baseCategory3Mapper.selectList(
                new LambdaQueryWrapper<BaseCategory3>()
                        .eq(BaseCategory3::getCategory2Id,c2Id));
    }

    @Resource
    private BaseAttrInfoMapper baseAttrInfoMapper;

    @Resource
    private BaseAttrValueMapper baseAttrValueMapper;
    /**
     * 保存平台属性表
     *
     * @param baseAttrInfo
     */
    @Override
    public void saveBaseAttrInfo(BaseAttrInfo baseAttrInfo) {
        //参数校验
        if(baseAttrInfo == null || StringUtils.isEmpty(baseAttrInfo.getAttrName())){
            throw new RuntimeException("参数不能为空");
        }
        //判断是新增还是修改
        if(baseAttrInfo.getId() == null){
            int insert = baseAttrInfoMapper.insert(baseAttrInfo);
            if(insert <= 0){
                throw new RuntimeException("新增平台属性名称失败!");
            }
        }else{
            int update = baseAttrInfoMapper.updateById(baseAttrInfo);
            if(update < 0){
                throw new RuntimeException("修改平台属性名称失败!");
            }
            //旧的平台属性值全删除
            int delete = baseAttrValueMapper.delete(
                    new LambdaQueryWrapper<BaseAttrValue>()
                            .eq(BaseAttrValue::getAttrId, baseAttrInfo.getId()));
            if(delete < 0){
                throw new RuntimeException("修改平台属性名称失败!");
            }
        }

        //新增成功 就能获取平台属性的ID
        Long attrId = baseAttrInfo.getId();
        //将id补充道平台属性每个值的对象中去
        List<BaseAttrValue> attrValueList
                = baseAttrInfo.getAttrValueList();
        attrValueList.stream().forEach(baseAttrValue -> {
            //补充平台属性的id
            baseAttrValue.setAttrId(attrId);
            //插入数据库
            int insert1 = baseAttrValueMapper.insert(baseAttrValue);
            if(insert1 <= 0){
                throw new RuntimeException("新增平台属性值失败!");
            }
        });
    }

    /**
     * 查询平台属性列表
     *
     * @param category1Id
     * @param category2Id
     * @param category3Id
     * @return
     */
    @Override
    public List<BaseAttrInfo> getBaseAttrInfo(Long category1Id, Long category2Id, Long category3Id) {
        return baseAttrInfoMapper.selectAttrInfoByCategoryId(category1Id,category2Id,category3Id);
    }

    /**
     * 查询平台值列表
     *
     * @param attrId
     * @return
     */
    @Override
    public List<BaseAttrValue> getBaseAttrValue(Long attrId) {
        return baseAttrValueMapper.selectList(
                new LambdaQueryWrapper<BaseAttrValue>()
                        .eq(BaseAttrValue::getAttrId,attrId));
    }

    @Resource
    private BaseTrademarkMapper baseTrademarkMapper;
    /**
     * 查询品牌列表
     *
     * @return
     */
    @Override
    public List<BaseTrademark> getBaseTrademark() {
        return baseTrademarkMapper.selectList(null);
    }

    @Resource
    private BaseSaleAttrMapper baseSaleAttrMapper;
    /**
     * 查询所有的销售属性
     *
     * @return
     */
    @Override
    public List<BaseSaleAttr> getBaseSaleAttr() {
        return baseSaleAttrMapper.selectList(null);
    }

    @Resource
    private SpuInfoMapper spuInfoMapper;
    /**
     * 保存spu的信息
     * @param spuInfo
     */
    @Override
    public void saveSpuInfo(SpuInfo spuInfo) {
        //参数校验
        if(spuInfo == null){
            throw new RuntimeException("参数不能为空,请重试");
        }
        //判断是新增还是修改
        if(spuInfo.getId() == null){
            //新增
            int insert = spuInfoMapper.insert(spuInfo);
            if(insert <= 0){
                throw new RuntimeException("插入失败,请重试");
            }
        }else{
            //修改
            int update = spuInfoMapper.updateById(spuInfo);
            if(update < 0){
                throw new RuntimeException("修改失败,请重试");
            }
            //附属表需要处理,删除图片表
            int delete = spuImageMapper.delete(
                    new LambdaQueryWrapper<SpuImage>()
                            .eq(SpuImage::getSpuId, spuInfo.getId()));
            //删除销售属性名称表
            int delete1 = spuSaleAttrMapper.delete(
                    new LambdaQueryWrapper<SpuSaleAttr>()
                            .eq(SpuSaleAttr::getSpuId, spuInfo.getId()));
            //删除销售属性值表 --TODO
            int delete2 = spuSaleAttrValueMapper.delete(
                    new LambdaQueryWrapper<SpuSaleAttrValue>()
                            .eq(SpuSaleAttrValue::getSpuId, spuInfo.getId()));
            if(delete<0 || delete1<0 || delete2<0){
                throw new RuntimeException("参数错误,修改失败");
            }
        }
        //获取spuID
        Long spuId = spuInfo.getId();
        //保存图片信息
        saveSpuImage(spuId,spuInfo.getSpuImageList());
        //保存spu销售信息 (saveSpuSaleAttr方法中保存spu值信息)
        saveSpuSaleAttr(spuId,spuInfo.getSpuSaleAttrList());
    }

    /**
     * 分页查询spuInfo信息
     *
     * @param page
     * @param size
     * @param category3Id
     * @return
     */
    @Override
    public IPage<SpuInfo> getSpuInfoList(Integer page, Integer size, Long category3Id) {
        return spuInfoMapper.selectPage(
                new Page<>(page,size),
                new LambdaQueryWrapper<SpuInfo>()
                        .eq(SpuInfo::getCategory3Id,category3Id));
    }

    /**
     * 查询品牌列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public IPage<BaseTrademark> getBaseTrademarkList(Integer page, Integer size) {
        return baseTrademarkMapper.selectPage(new Page<>(page,size),null);
    }

    /**
     * 根据Id回显品牌
     *
     * @param id
     * @return
     */
    @Override
    public BaseTrademark getBaseTrademarkById(Long id) {
        return baseTrademarkMapper.selectById(id);
    }

    /**
     * 根据Id删除品牌
     *
     * @param id
     */
    @Override
    public void deleteBaseTrademarkById(Long id) {
        int delete = baseTrademarkMapper.deleteById(id);
        if(delete < 0){
            throw new RuntimeException("删除失败,请重试");
        }
    }

    /**
     * 根据Id修改
     *
     * @param baseTrademark
     */
    @Override
    public void updateBaseTrademark(BaseTrademark baseTrademark) {
        int update = baseTrademarkMapper.updateById(baseTrademark);
        if(update < 0){
            throw new RuntimeException("修改失败,请重试");
        }
    }

    /**
     * 新增品牌
     *
     * @param baseTrademark
     */
    @Override
    public void saveBaseTrademark(BaseTrademark baseTrademark) {
        int insert = baseTrademarkMapper.insert(baseTrademark);
        if(insert < 0){
            throw new RuntimeException("新增失败,请重试");
        }
    }

    /**
     * 根据spuId查询所有的销售属性信息
     *
     * @param spuId
     * @return
     */
    @Override
    public List<SpuSaleAttr> getSpuSaleAttr(Long spuId) {
        return spuSaleAttrMapper.selectSpuSaleAttrBySpuId(spuId);
    }

    /**
     * 根据spuId查询图片
     *
     * @param spuId
     * @return
     */
    @Override
    public List<SpuImage> getSpuImage(Long spuId) {
        return spuImageMapper.selectList(
                new LambdaQueryWrapper<SpuImage>()
                        .eq(SpuImage::getSpuId,spuId));
    }

    @Resource
    private SkuInfoMapper skuInfoMapper;

    /**
     * 分页查询sku信息
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public IPage<SkuInfo> skuInfoList(Integer page, Integer size) {
        return skuInfoMapper.selectPage(new Page<>(page,size),null);
    }

    /**
     * 保存skuInfo信息
     *
     * @param skuInfo
     */
    @Override
    public void saveSkuInfo(SkuInfo skuInfo) {
        //参数校验
        if(skuInfo == null || StringUtils.isEmpty(skuInfo.getSkuDefaultImg())){
            throw new RuntimeException("保存失败,请重试");
        }
        //判断是新增还是修改
        if(skuInfo.getId() == null){
            //新增
            int insert = skuInfoMapper.insert(skuInfo);
            if(insert <= 0){
                throw new RuntimeException("新增失败");
            }
        }else{
            //修改
            int update = skuInfoMapper.updateById(skuInfo);
            if(update < 0){
                throw new RuntimeException("修改失败");
            }
            //删除sku的图片信息
            int delete = skuImageMapper.delete(
                    new LambdaQueryWrapper<SkuImage>()
                            .eq(SkuImage::getSkuId, skuInfo.getId()));
            //删除sku的销售属性
            int delete1 = skuSaleAttrValueMapper.delete(
                    new LambdaQueryWrapper<SkuSaleAttrValue>()
                            .eq(SkuSaleAttrValue::getSkuId, skuInfo.getId()));
            //删除sku的平台属性
            int delete2 = skuAttrValueMapper.delete(
                    new LambdaQueryWrapper<SkuAttrValue>()
                            .eq(SkuAttrValue::getSkuId, skuInfo.getId()));
            //判断
            if(delete<0 || delete1<0 ||delete2<0){
                throw new RuntimeException("修改sku失败");
            }
        }
        //获取skuId
        Long skuId = skuInfo.getId();
        //保存sku的图片信息
        saveSkuImage(skuId,skuInfo.getSkuImageList());
        //保存sku的销售属性
        saveSkuSaleAttrValue(skuId,skuInfo.getSkuSaleAttrValueList(),skuInfo.getSpuId());
        //保存sku的平台属性
        saveSkuAttrValue(skuId,skuInfo.getSkuAttrValueList());
    }

    @Autowired
    private GoodsFeign goodsFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    /**
     * 商品图片上架或者下架
     *
     * @param skuId
     * @param status
     */
    @Override
    public void upOrDown(Long skuId,Short status) {
        //参数校验
        if(skuId == null){
            return;
        }
        //查询sku信息---方案一------------------TODO----待优化---等分布式锁学完回来优化!!!!--时间差
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if(skuInfo==null ||skuInfo.getId()==null){
            return;
        }
        //改变IsSale字段
        skuInfo.setIsSale(status);
        //修改
        int update = skuInfoMapper.updateById(skuInfo);
        if(update<0){
            throw new RuntimeException("上架或下架失败!");
        }

        //定制化的return模式:记录日志
        rabbitTemplate.setReturnCallback((a,b,c,d,e)->{
            log.error("商品上下架消息发送失败,消息内容为: "+new String(a.getBody()));
            log.error("商品上下架消息发送失败,错误码为 : "+ b);
            log.error("商品上下架消息发送失败,错误内容为 : "+ c);
            log.error("商品上下架消息发送失败,交换机为 : "+ d);
            log.error("商品上下架消息发送失败,RoutingKey为: "+ e);
        });

        //判断商品为上架还是下架---------------存在数据不一致的情况待优化
        /*if(status.equals(ProductConst.SKU_ON_SALE)){
            //上架
            goodsFeign.add(skuId);
        }else{
            //下架
            goodsFeign.remove(skuId);
        }*/

        //判断商品为上架还是下架 使用消息队列 避免了数据不一致的情况
        if(status.equals(ProductConst.SKU_ON_SALE)){
            //上架
            rabbitTemplate.convertAndSend("sku_exchange","sku.upper",skuId+"");
        }else{
            //下架
            rabbitTemplate.convertAndSend("sku_exchange","sku.down",skuId+"");
        }

        //方案二
        /*int i = skuInfoMapper.upOrDown(skuId, status);
        if(i < 0){
            throw new RuntimeException("上架或下架失败!");
        }*/
    }

    @Resource
    private SkuAttrValueMapper skuAttrValueMapper;
    /**
     * 保存sku的平台属性
     * @param skuId
     * @param skuAttrValueList
     */
    private void saveSkuAttrValue(Long skuId, List<SkuAttrValue> skuAttrValueList) {
        skuAttrValueList.stream().forEach(skuAttrValue -> {
            //补全skuId
            skuAttrValue.setSkuId(skuId);
            //插入
            int insert = skuAttrValueMapper.insert(skuAttrValue);
            if(insert <= 0){
                throw new RuntimeException("保存sku的平台属性是吧");
            }
        });
    }

    @Resource
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;
    /**
     * 保存sku的销售属性
     * @param skuId
     * @param skuSaleAttrValueList
     * @param spuId
     */
    private void saveSkuSaleAttrValue(Long skuId, List<SkuSaleAttrValue> skuSaleAttrValueList, Long spuId) {
        skuSaleAttrValueList.stream().forEach(skuSaleAttrValue -> {
            //补全skuId
            skuSaleAttrValue.setSkuId(skuId);
            //补全spuId
            skuSaleAttrValue.setSpuId(spuId);
            //插入
            int insert = skuSaleAttrValueMapper.insert(skuSaleAttrValue);
            if(insert <= 0){
                throw new RuntimeException("新增sku销售属性失败");
            }
        });
    }

    @Resource
    private SkuImageMapper skuImageMapper;
    /**
     * 保存sku的图片信息
     * @param skuId
     * @param skuImageList
     */
    private void saveSkuImage(Long skuId, List<SkuImage> skuImageList) {
        skuImageList.stream().forEach(skuImage -> {
            //补全skuId
            skuImage.setSkuId(skuId);
            //插入
            int insert = skuImageMapper.insert(skuImage);
            if(insert <= 0){
                throw new RuntimeException("新增图片失败");
            }
        });
    }

    @Resource
    private SpuSaleAttrMapper spuSaleAttrMapper;
    /**
     * 保存spu的销售属性信息
     * @param spuId
     * @param spuSaleAttrList
     */
    private void saveSpuSaleAttr(Long spuId,List<SpuSaleAttr> spuSaleAttrList){
        spuSaleAttrList.stream().forEach(spuSaleAttr -> {
            //补全spuId
            spuSaleAttr.setSpuId(spuId);
            //保存spu的销售信息
            int insert = spuSaleAttrMapper.insert(spuSaleAttr);
            if(insert <= 0){
                throw new RuntimeException("保存销售信息失败,请重试");
            }
            //保存销售值
            saveSpuSaleAttrValue(spuId,spuSaleAttr.getSpuSaleAttrValueList(),spuSaleAttr.getSaleAttrName());
        });
    }

    @Resource
    private SpuSaleAttrValueMapper spuSaleAttrValueMapper;
    /**
     *保存销售属性值
     * @param spuId
     * @param spuSaleAttrValueList
     */
    private void saveSpuSaleAttrValue(Long spuId,List<SpuSaleAttrValue> spuSaleAttrValueList,String saleAttrName){
        spuSaleAttrValueList.stream().forEach(spuSaleAttrValue -> {
            //补全spuId
            spuSaleAttrValue.setSpuId(spuId);
            //补全saleAttrName
            spuSaleAttrValue.setSaleAttrName(saleAttrName);
            //保存spu的销售值
            int insert = spuSaleAttrValueMapper.insert(spuSaleAttrValue);
            if(insert <= 0){
                throw new RuntimeException("保存属性值失败,请重试");
            }
        });
    }

    @Resource
    private SpuImageMapper spuImageMapper;
    /**
     * 保存图片信息
     * @param spuId
     * @param spuImageList
     */
    private void saveSpuImage(Long spuId,List<SpuImage>spuImageList){
        spuImageList.stream().forEach(spuImage -> {
            //补全spuId
            spuImage.setSpuId(spuId);
            //保存图片信息
            int insert = spuImageMapper.insert(spuImage);
            if(insert <= 0){
                throw new RuntimeException("插入图片失败,请重试");
            }
        });
    }
}
